package cn.wolfcode.car.business.service.impl;

import cn.wolfcode.car.business.domain.BpmnInfo;
import cn.wolfcode.car.business.domain.CarPackageAudit;
import cn.wolfcode.car.business.domain.ServiceItem;
import cn.wolfcode.car.business.mapper.ServiceItemMapper;
import cn.wolfcode.car.business.query.ServiceItemQuery;
import cn.wolfcode.car.business.service.IBpmnInfoService;
import cn.wolfcode.car.business.service.ICarPackageAuditService;
import cn.wolfcode.car.business.service.IServiceItemService;
import cn.wolfcode.car.common.base.page.TablePageInfo;
import cn.wolfcode.car.common.exception.BusinessException;
import cn.wolfcode.car.shiro.ShiroUtils;
import com.github.pagehelper.PageHelper;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.runtime.ProcessInstance;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;

@Service
public class ServiceItemServiceImpl implements IServiceItemService {
    @Autowired
    private ServiceItemMapper serviceItemMapper;
    @Autowired
    private ICarPackageAuditService carPackageAuditService;
    @Autowired
    private IBpmnInfoService bpmnInfoService;
    @Autowired
    private RuntimeService runtimeService;
    @Override
    public TablePageInfo<ServiceItem> query(ServiceItemQuery qo) {
        PageHelper.startPage(qo.getPageNum(), qo.getPageSize());
        return new TablePageInfo<ServiceItem>(serviceItemMapper.selectForList(qo));
    }

    @Override
    public void save(ServiceItem serviceItem) {
        //从安全角度考虑,前台传递过来的对象是不能直接使用的
        //所以我们都新建对象.这样无论如何都不会因为前台传递了默认值而改变我们默认值数据
        ServiceItem newObj = new ServiceItem();
        newObj.setName(serviceItem.getName());                      //服务项名称
        newObj.setOriginalPrice(serviceItem.getOriginalPrice());    //服务项原价
        newObj.setDiscountPrice(serviceItem.getDiscountPrice());    //服务项折扣价
        newObj.setCarPackage(serviceItem.getCarPackage());          //是否套餐【是/否】
        newObj.setInfo(serviceItem.getInfo());                      //备注信息
        newObj.setCreateTime(new Date());                           //创建时间
        newObj.setServiceCatalog(serviceItem.getServiceCatalog());  //服务分类【维修/保养/其他】
        //新增分为套餐 和非套餐
        if (ServiceItem.CARPACKAGE_YES.equals(newObj.getCarPackage())){
            //是套餐默认审核状态-->初始化
            newObj.setAuditStatus(ServiceItem.AUDITSTATUS_INIT);
        }else {
            //不是套餐默认审核状态-->无需审核
            newObj.setAuditStatus(ServiceItem.AUDITSTATUS_NO_REQUIRED);
        }
        serviceItemMapper.insert(newObj);
    }

    @Override
    public ServiceItem get(Long id) {
        return serviceItemMapper.selectByPrimaryKey(id);
    }

    @Override
    public void update(ServiceItem serviceItem) {
       ServiceItem oldObj =  this.get(serviceItem.getId());
        //处于上架状态的商品不能修改
        if (ServiceItem.SALESTATUS_ON.equals(oldObj.getSaleStatus())){
            throw new BusinessException("上架服务项目无法修改,请下架后再修改");
        }
        //审核中 状态 无法修改
        if (ServiceItem.AUDITSTATUS_AUDITING.equals(oldObj.getAuditStatus())){
            throw new BusinessException("审核中服务项目无法修改,请审核通过后再修改");
        }
        //若是审核通过 此时修改,需要将其状态变更为初始化
        if (ServiceItem.AUDITSTATUS_APPROVED.equals(oldObj.getAuditStatus())){
            serviceItem.setAuditStatus(ServiceItem.AUDITSTATUS_INIT);
        }
        oldObj.setName(serviceItem.getName());                      //服务项名称
        oldObj.setOriginalPrice(serviceItem.getOriginalPrice());    //服务项原价
        oldObj.setDiscountPrice(serviceItem.getDiscountPrice());    //服务项折扣价
        //oldObj.setCarPackage(serviceItem.getCarPackage());          //是否套餐【是/否】
        oldObj.setInfo(serviceItem.getInfo());                      //备注信息
        //oldObj.setCreateTime(new Date());                           //创建时间
        oldObj.setServiceCatalog(serviceItem.getServiceCatalog());  //服务分类【维修/保养/其他】
        serviceItemMapper.updateByPrimaryKey(oldObj);
    }

    @Override
    public void saleOn(Long id) {
        //根据服务单项id 查询当前服务单项对象
        ServiceItem oldObj =  this.get(id);

        if (oldObj!=null){
            //处于上架状态,不需要任何操作
            if (ServiceItem.SALESTATUS_ON.equals(oldObj.getSaleStatus())) {
                throw new BusinessException("该服务项目处于上架状态,无需重复操作");
            }
            //若是套餐必须是审核通过状态才可以上架
            if (ServiceItem.CARPACKAGE_YES.equals(oldObj.getCarPackage())&&
                    !ServiceItem.AUDITSTATUS_APPROVED.equals(oldObj.getAuditStatus())){
                throw new BusinessException("未审核通过,无法上架");
            }
            //其余情况可以上架
            serviceItemMapper.updateSaleStatus(id,ServiceItem.SALESTATUS_ON);
        }

    }

    @Override
    public void saleOff(Long id) {
        serviceItemMapper.updateSaleStatus(id,ServiceItem.SALESTATUS_OFF);
    }

    @Override
    public void startAudit(Long id, Long showOwnerId, Long financeId, String info) {
        ServiceItem serviceItem = this.get(id);
        //必须是套餐类型
        if (!ServiceItem.CARPACKAGE_YES.equals(serviceItem.getCarPackage())){
            throw  new BusinessException("只有套餐才能发起审核");
        }
        //确认套餐
        if (ServiceItem.AUDITSTATUS_AUDITING.equals(serviceItem.getAuditStatus())||
                ServiceItem.AUDITSTATUS_APPROVED.equals(serviceItem.getAuditStatus())){
            throw new BusinessException("非法状态");
        }
        // 需要封装 CarPackageAudit 封装对象信息。
        CarPackageAudit audit = new CarPackageAudit();
        audit.setServiceItemId(serviceItem.getId()); //服务单项id
        audit.setServiceItemName(serviceItem.getName());//服务单项名字
        audit.setServiceItemInfo(serviceItem.getInfo());//服务单项备注
        audit.setServiceItemPrice(serviceItem.getDiscountPrice());//服务单项折扣价
        audit.setCreatorId(ShiroUtils.getUserId().toString());//创建者
        audit.setCreateTime(new Date());//创建时间
        audit.setInfo(info);//发起审核的备注信息
        carPackageAuditService.save(audit);
        // 获取插入数据库中的CarPackageAudit的id 值，这样就拿到了 BusinessKey
        String businessKey = audit.getId().toString();
        // 如何能找到对应的流程定义，发起流程实例 （也就是我们发起的流程）
        // 通过 CarpackageAudit.AUDIT_TYPE 属性去 bpmnInfo 表中查询对应的 流程定义 Key
        BpmnInfo bpmnInfo = bpmnInfoService.getByBpmnType(CarPackageAudit.AUDIT_TYPE);
        // 若查询结果为 Null,说明没有上传该流程定义。
        // 若查询到多个，按部署时间最近的那个（版本号最高的）
        if (bpmnInfo == null){
                throw new BusinessException("请上传流程定义");
        }
        // 发起流程时我们需要携带什么样的参数到流程中（给连线和节点上的流程变量赋值）
        // 需要定义一个 Map 集合，存储任务负责人相关 id (店长、财务)，折扣金额
        // 启动流程实例，在启动的同时绑定 Businesskey 与 流程变量的 Map 一并传入
        String processDefinitionKey = bpmnInfo.getProcessDefinitionKey();
        Map<String,Object> params = new HashMap<>();
        params.put("shopOwnerId",showOwnerId); //店长
        if (financeId != null){
            params.put("financeId",financeId);
        }
        params.put("disCountPrice",serviceItem.getDiscountPrice().longValue());//折扣价
        //启动流程实例
        ProcessInstance processInstance = runtimeService.startProcessInstanceByKey(processDefinitionKey, businessKey, params);
        // 为 CarPackageAudit 插入流程实例 id。
        audit.setInstanceId(processInstance.getProcessInstanceId());
        carPackageAuditService.update(audit);
        // 服务单项中的状态改编为 审核中。
        serviceItemMapper.changeAuditStatus(serviceItem.getId(),ServiceItem.AUDITSTATUS_AUDITING);
    }

    @Override
    public void changeAuditStatus(Long serviceItemId, Integer auditstatusInit) {
        serviceItemMapper.changeAuditStatus(serviceItemId,auditstatusInit);
    }
}
